package jmine.tec.utils;

import java.lang.reflect.Method;

/**
 * Metodos utilitarios para chamadas reflexivas.
 * 
 * @author takeshi
 */
public final class ReflectiveMethodUtils {

    /**
     * C'tor
     */
    private ReflectiveMethodUtils() {
    }

    /**
     * Devolve true se este metodo pertence a object ou for um metodo sobrescrito de {@link Object}
     * 
     * @param m the method
     * @return boolean
     */
    public static boolean isObjectMethod(Method m) {
        return m.getDeclaringClass().equals(Object.class) || isToStringMethod(m) || isHashCodeMethod(m) || isFinalizeMethod(m)
                || isCloneMethod(m) || isEqualsMethod(m);
    }

    /**
     * Devolve <code>true</code> se o {@link Method} eh o {@link Object#toString()}
     * 
     * @param method Method
     * @return boolean
     */
    public static boolean isEqualsMethod(Method method) {
        final Class<?>[] parameterTypes = method.getParameterTypes();
        return method.getName().equals("equals") && boolean.class == method.getReturnType() && parameterTypes.length == 1
                && Object.class == parameterTypes[0];
    }

    /**
     * Devolve <code>true</code> se o {@link Method} eh o {@link Object#toString()}
     * 
     * @param method Method
     * @return boolean
     */
    public static boolean isToStringMethod(Method method) {
        return method.getName().equals("toString") && String.class.isAssignableFrom(method.getReturnType()) && isZeroArgumentMethod(method);
    }

    /**
     * Devolve <code>true</code> se o {@link Method} eh o {@link Object#hashCode()}
     * 
     * @param method Method
     * @return boolean
     */
    public static boolean isHashCodeMethod(Method method) {
        return method.getName().equals("hashCode") && int.class == method.getReturnType() && isZeroArgumentMethod(method);
    }

    /**
     * Devolve <code>true</code> se o {@link Method} eh o {@link Object#finalize()}
     * 
     * @param method Method
     * @return boolean
     */
    public static boolean isFinalizeMethod(Method method) {
        return method.getName().equals("finalize") && void.class == method.getReturnType() && isZeroArgumentMethod(method);
    }

    /**
     * Devolve <code>true</code> se o {@link Method} eh o {@link Object#clone()}
     * 
     * @param method Method
     * @return boolean
     */
    public static boolean isCloneMethod(Method method) {
        return method.getName().equals("clone") && isZeroArgumentMethod(method);
    }

    /**
     * Devolve <code>true</code> se o {@link Method} nao recebe nenhum argumento
     * 
     * @param method Method
     * @return boolean
     */
    public static boolean isZeroArgumentMethod(Method method) {
        return method.getParameterTypes().length == 0;
    }

}
